package com.nf.mvc.handler;

import com.nf.mvc.HandlerMapping;
import com.nf.mvc.argument.MethodParameter;
import com.nf.mvc.mapping.RequestMappingHandlerMapping;
import com.nf.mvc.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.List;

/**
 * 此类是一个对请求处理方法进行封装的类型。典型的Mvc框架中的Handler就是由此类型代表
 * <p>既然用到此类，就表明是有方法的，所以父类注释中说的4种情况，只有2种情况是需要本类处理的：
 *     <ul>
 *         <li>有HandlerClass，有方法，对应{@link #HandlerMethod(Method)}</li>
 *         <li>有Handler对象，有方法，对应{@link #HandlerMethod(Object, Method)}</li>
 *     </ul>
 * </p>
 */
public class HandlerMethod extends HandlerClass {

    private final Method method;

    private MethodParameter[] methodParameters;

    public HandlerMethod(Method method) {
        super(method.getDeclaringClass());
        this.method = method;
        initMethodParameters();
    }

    public HandlerMethod(Object handlerObject, Method method) {
        super(handlerObject);
        this.method = method;
        initMethodParameters();
    }

    private void initMethodParameters() {
        List<String> paramNames = ReflectionUtils.getParameterNames(method);
        int parameterCount = method.getParameterCount();
        methodParameters = new MethodParameter[parameterCount];
        for (int i = 0; i < parameterCount; i++) {
            MethodParameter methodParameter = new MethodParameter(method, i, paramNames.get(i));
            methodParameters[i] = methodParameter;
        }
    }

    public String getMethodName() {
        return method.getName();
    }

    public Method getMethod() {
        return method;
    }

    public MethodParameter[] getMethodParameters() {
        return methodParameters;
    }

    public int getParameterCount() {
        return method.getParameterCount();
    }

    /**
     * 重写此方法是为了更好的显示handler的描述信息，可以用在{@link HandlerMapping}
     * 的实现类中，见{@link RequestMappingHandlerMapping#addHandler(String, HandlerMethod)}
     *
     * @return handler所在方法名以及所在的类名
     */
    @Override
    public String toString() {
        return "当前handler的方法名是:" + getMethodName()
                + " 所在类的名字是:" + getHandlerClass().getName();
    }
}


